package com.leve.admin.common;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.net.URL;
import java.nio.charset.Charset;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.List;


/**
 * 简单HTTP请求
 * <p>
 * 简单对HttpClient库做封装接口中使用。
 * 只有POST与GET的简单请求，没有其它header设置等一些复杂功能
 */
public class HTTPSimple {
    private static String charset = "UTF-8";


    public static String PUT(String url, String jsondata) {
        String responseContext = "";
        try {
            CloseableHttpClient httpclient = getClientInstance(url);
            HttpPut httpPut = new HttpPut(url);
            httpPut.addHeader("Content-type", "application/json; charset=" + charset);
            httpPut.setHeader("Accept", "application/json");

            httpPut.setEntity(new StringEntity(jsondata, Charset.forName(charset)));

            CloseableHttpResponse response = httpclient.execute(httpPut);

            int status = response.getStatusLine().getStatusCode();
            if ((status > 300) && (status < 310)) {
                Header[] h = response.getHeaders("Location");
                if (h.length > 0) {
                    httpclient.close();
                    return POST(h[0].toString().substring(10), jsondata);
                }
            }
            HttpEntity entity = response.getEntity();
            responseContext = EntityUtils.toString(entity, charset);
            EntityUtils.consume(entity);
            httpclient.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return responseContext;
    }

    /*
     * HTTP的GET请求
     *
     * @param	String 请求的URL地址
     * @return	String 返回内容
     */
    public static String GET(String url) {
        String responseContext = "";
        try {
            CloseableHttpClient httpclient = HTTPSimple.getClientInstance(url);
            HttpGet httpGet = new HttpGet(url);
            CloseableHttpResponse response = httpclient.execute(httpGet);
            int status = response.getStatusLine().getStatusCode();
            if (status > 300 && status < 310) {
                Header[] h = response.getHeaders("Location");
                if (h.length > 0) {
                    httpclient.close();
                    return HTTPSimple.GET(h[0].toString().substring(10));
                }
            }
            HttpEntity entity = response.getEntity();
            responseContext = EntityUtils.toString(entity, charset);
            EntityUtils.consume(entity);
            httpclient.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return responseContext;
    }


    /*
     * HTTP的delete请求
     *
     * @param	String 请求的URL地址
     * @return	String 返回内容
     */
    public static String delete(String url) {
        String responseContext = "";
        try {
            CloseableHttpClient httpclient = HTTPSimple.getClientInstance(url);
            HttpDelete Httpdelete = new HttpDelete(url);
            CloseableHttpResponse response = httpclient.execute(Httpdelete);
            int status = response.getStatusLine().getStatusCode();
            if (status > 300 && status < 310) {
                Header[] h = response.getHeaders("Location");
                if (h.length > 0) {
                    httpclient.close();
                    return HTTPSimple.delete(h[0].toString().substring(10));
                }
            }
            HttpEntity entity = response.getEntity();
            responseContext = EntityUtils.toString(entity, charset);
            EntityUtils.consume(entity);
            httpclient.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return responseContext;
    }

    /**
     * HTTP的POST请求
     *
     * @param url      String 请求的URL地址
     * @param jsondata json数据
     * @return 返回内容
     */
    public static String POST(String url, String jsondata) {

        String responseContext = "";
        try {
            CloseableHttpClient httpclient = HTTPSimple.getClientInstance(url);
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("Content-type", "application/json; charset=" + charset);
            httpPost.setHeader("Accept", "application/json");

            httpPost.setEntity(new StringEntity(jsondata, Charset.forName(charset)));

            CloseableHttpResponse response = httpclient.execute(httpPost);

            int status = response.getStatusLine().getStatusCode();
            if (status > 300 && status < 310) {
                Header[] h = response.getHeaders("Location");
                if (h.length > 0) {
                    httpclient.close();
                    return HTTPSimple.POST(h[0].toString().substring(10), jsondata);
                }
            }
            HttpEntity entity = response.getEntity();
            responseContext = EntityUtils.toString(entity, charset);
            EntityUtils.consume(entity);
            httpclient.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return responseContext;

    }

    /*
     * HTTP的put请求
     *
     * @param	String 请求的URL地址
     * @return	String 返回内容
     */
    public static String put(String url) {
        String responseContext = "";
        try {
            CloseableHttpClient httpclient = HTTPSimple.getClientInstance(url);
            HttpPut httpPut = new HttpPut(url);
            CloseableHttpResponse response = httpclient.execute(httpPut);
            int status = response.getStatusLine().getStatusCode();
            if (status > 300 && status < 310) {
                Header[] h = response.getHeaders("Location");
                if (h.length > 0) {
                    httpclient.close();
                    return HTTPSimple.put(h[0].toString().substring(10));
                }
            }
            HttpEntity entity = response.getEntity();
            responseContext = EntityUtils.toString(entity, charset);
            EntityUtils.consume(entity);
            httpclient.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return responseContext;
    }

    /**
     * HTTP的POST请求
     *
     * @return String 返回内容
     */
    public static String POST(String url, List<NameValuePair> param) {
        String responseContext = "";
        int found = url.indexOf('?');
        if (found > 0) {
            url = url.substring(0, found);
        }
        try {
            CloseableHttpClient httpclient = HTTPSimple.getClientInstance(url);
            HttpPost httpPost = new HttpPost(url);
            httpPost.setEntity(new UrlEncodedFormEntity(param, Charset.forName(charset)));
            CloseableHttpResponse response = httpclient.execute(httpPost);
            int status = response.getStatusLine().getStatusCode();
            if (status > 300 && status < 310) {
                Header[] h = response.getHeaders("Location");
                if (h.length > 0) {
                    httpclient.close();
                    return HTTPSimple.POST(h[0].toString().substring(10), param);
                }
            }
            HttpEntity entity = response.getEntity();
            responseContext = EntityUtils.toString(entity, charset);
            EntityUtils.consume(entity);
            httpclient.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return responseContext;
    }

    /**
     * 通过URL地址验证是否HTTPS安全链接
     *
     * @return boolean
     */
    private static boolean isSecurity(String url) throws Exception {
        URL u = new URL(url);
        return u.getProtocol().contentEquals("https");
    }


    /**
     * 微信专用SSL
     *
     * @param keyStore
     * @param mch_id
     * @param url
     * @return
     * @throws Exception
     */
    private static CloseableHttpClient getClientInstanceForPKCS12(KeyStore keyStore,
                                                                  String mch_id, String url) throws Exception {
        CloseableHttpClient httpclient = null;
        if (keyStore != null && HTTPSimple.isSecurity(url)) {
            SSLContext sslcontext =
                    SSLContexts.custom()
                            .loadKeyMaterial(keyStore, mch_id.toCharArray())
                            .build();

            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslcontext,
                    new String[]{"TLSv1"},
                    null,
                    SSLConnectionSocketFactory.getDefaultHostnameVerifier()
            );

//			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
//	                sslcontext,
//	                new String[] { "TLSv1" },
//	                null,
//	                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

            httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        } else {
            httpclient = getClientInstance(url);//HttpClients.createDefault();
        }
        return httpclient;
    }


    /**
     * 初始化HttpClient对象
     * <p>
     * 若url为https链接，则使用SSLConnection来初始化
     * 若为普通的HTTP链接，只使用默认的HttpClient参数初始化
     *
     * @return CloseableHttpClient
     */
    private static CloseableHttpClient getClientInstance(String url) throws Exception {
        CloseableHttpClient httpclient = null;
        if (HTTPSimple.isSecurity(url)) {
            KeyStore myTrustKeyStore = KeyStore.getInstance(
                    KeyStore.getDefaultType()
            );
            SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(myTrustKeyStore, new TrustStrategy() {
                @Override
                public boolean isTrusted(final X509Certificate[] chain, final String authType) throws CertificateException {
                    return true;
                }
            }).build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslcontext,
                    new String[]{"TLSv1"},
                    null,
                    SSLConnectionSocketFactory.getDefaultHostnameVerifier()
            );
            httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        } else {
            httpclient = HttpClients.createDefault();
        }
        return httpclient;
    }


    /**
     * 初始化HttpClient对象
     * <p>
     * 若url为https链接，则使用SSLConnection来初始化
     * 若为普通的HTTP链接，只使用默认的HttpClient参数初始化
     *
     * @return CloseableHttpClient
     */
    private static CloseableHttpClient getClientInstance(KeyStore keyStore, String url) throws Exception {
        CloseableHttpClient httpclient = null;
        if (HTTPSimple.isSecurity(url)) {
//			KeyStore myTrustKeyStore = KeyStore.getInstance(
//				KeyStore.getDefaultType()
//			);
            SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(keyStore, new TrustStrategy() {
                @Override
                public boolean isTrusted(final X509Certificate[] chain, final String authType) throws CertificateException {
                    return true;
                }
            }).build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslcontext,
                    new String[]{"TLSv1"},
                    null,
                    SSLConnectionSocketFactory.getDefaultHostnameVerifier()
            );
            httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        } else {
            httpclient = HttpClients.createDefault();
        }
        return httpclient;
    }

    public static String getCharset() {
        return charset;
    }


    public static void setCharset(String scharset) {
        charset = scharset;
    }
}